package com.xiguaji.tiktok.v1.ins.rank.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.xiguaji.boot.toolkit.jdbc.Page;
import com.xiguaji.tiktok.v1.ins.brand.repository.CommonBrandRepository;
import com.xiguaji.tiktok.v1.ins.rank.dto.BrandRankDto;
import com.xiguaji.tiktok.v1.ins.rank.dto.InsRkSearch;
import com.xiguaji.tiktok.v1.ins.rank.dto.ProductRankDto;
import com.xiguaji.tiktok.v1.ins.rank.dto.RankDto;
import com.xiguaji.tiktok.v1.ins.rank.repository.*;
import lombok.val;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class InsRankService {

    @Autowired
    InsRkBloggerFlMonthRepository insRkBloggerFlMonthRepository;

    @Autowired
    InsRkBloggerFgDayRepository insRkBloggerFgDayRepository;

    @Autowired
    InsRkBloggerFgWeekRepository insRkBloggerFgWeekRepository;

    @Autowired
    InsRkBloggerFgMonthRepository insRkBloggerFgMonthRepository;

    @Autowired
    InsRkBloggerAdecWeekRepository insRkBloggerAdecWeekRepository;

    @Autowired
    InsRkBloggerAdecMonthRepository insRkBloggerAdecMonthRepository;

    @Autowired
    InsRkProductMonthRepository insRkProductMonthRepository;

    @Autowired
    InsRkProductWeekRepository insRkProductWeekRepository;

    @Autowired
    InsRkBrandDayRepository insRkBrandDayRepository;

    @Autowired
    InsRkBrandWeekRepository insRkBrandWeekRepository;

    @Autowired
    InsRkBrandMonthRepository insRkBrandMonthRepository;

    @Autowired
    InsRkBloggerBgsDayRepository insRkBloggerBgsDayRepository;

    @Autowired
    InsRkBloggerBgsWeekRepository insRkBloggerBgsWeekRepository;

    @Autowired
    InsRkBloggerBgsMonthRepository insRkBloggerBgsMonthRepository;

    @Autowired
    CommonBrandRepository commonBrandRepository;

    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MMM dd, yyyy", Locale.ENGLISH);

    final int RANK_DATE_DAY_SIZE = 7;
    final int RANK_DATE_WEEK_SIZE = 4;
    final int RANK_DATE_MONTH_SIZE = 3;

    /**
     * 粉丝排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByFollowerRank(String category,String nation){
        return insRkBloggerFlMonthRepository.getMaxCreateTime(category,nation);
    }

    /**
     * 粉丝排行榜最新排行时间
     * @return
     */
    public int getUpdateDateCodeByFollowerRank(String category,String nation){
        return insRkBloggerFlMonthRepository.getMxDateCode(category,nation);
    }

    /**
     * 分页
     * @return
     */
    public Page<RankDto> getFollowerRankPage(InsRkSearch followerSearch){
        return insRkBloggerFlMonthRepository.findPage(followerSearch);
    }

    /**
     * 列表
     * @return
     */
    public List<RankDto> getFollowerRankList(InsRkSearch followerSearch){
        return insRkBloggerFlMonthRepository.findList(followerSearch);
    }

    /**
     * 粉丝增长天排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByFgDayRank(String category){
        return insRkBloggerFgDayRepository.getMaxCreateTime(category);
    }

    public int getDayMaxDateCode(String category){
        return insRkBloggerFgDayRepository.getMaxDateCode(category);
    }

    /**
     * 粉丝增长天排行榜分页
     * @return
     */
    public Page<RankDto> getFgDayRankPage(InsRkSearch followerSearch){
        return insRkBloggerFgDayRepository.findPage(followerSearch);
    }

    /**
     * 粉丝增长天排行榜列表
     * @return
     */
    public List<RankDto> getFgDayRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerFgDayRepository.findList(followerSearch,size);
    }

    /**
     * 粉丝增长周排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByFgWeekRank(String category){
        return insRkBloggerFgWeekRepository.getMaxCreateTime(category);
    }

    /**
     * 粉丝增长周排行榜分页
     * @return
     */
    public Page<RankDto> getFgWeekRankPage(InsRkSearch followerSearch){
        return insRkBloggerFgWeekRepository.findPage(followerSearch);
    }

    /**
     * 粉丝增长周排行榜列表
     * @return
     */
    public List<RankDto> getFgWeekRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerFgWeekRepository.findList(followerSearch,size);
    }

    /**
     * 粉丝增长月排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByFgMonthRank(String category){
        return insRkBloggerFgMonthRepository.getMaxCreateTime(category);
    }

    /**
     * 粉丝增长月排行榜分页
     * @return
     */
    public Page<RankDto> getFgMonthRankPage(InsRkSearch followerSearch){
        return insRkBloggerFgMonthRepository.findPage(followerSearch);
    }

    /**
     * 粉丝增长月排行榜列表
     * @return
     */
    public List<RankDto> getFgMonthRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerFgMonthRepository.findList(followerSearch,size);
    }


    //########品牌
    /**
     * 品牌天排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBrandDayRank(String category){
        return insRkBrandDayRepository.getMaxCreateTime(category);
    }

    public int getBrandNewestDateCode(InsRkSearch insRkSearch){
        if(insRkSearch.getRankType() == 1){
            return insRkBrandWeekRepository.getMaxDateCode(insRkSearch.getCategoryName());
        }else if(insRkSearch.getRankType() == 2){
            return insRkBrandMonthRepository.getMaxDateCode(insRkSearch.getCategoryName());
        }
        return insRkBrandDayRepository.getMaxDateCode(insRkSearch.getCategoryName());
    }

    /**
     * 品牌天排行榜分页
     * @return
     */
    public Page<BrandRankDto> getBrandDayRankPage(InsRkSearch followerSearch){
        return getBrandLogo(insRkBrandDayRepository.findPage(followerSearch));
    }

    /**
     * 品牌天排行榜列表
     * @return
     */
    public List<BrandRankDto> getBrandDayRankList(InsRkSearch followerSearch,int size){
        return insRkBrandDayRepository.findList(followerSearch,size);
    }

    /**
     * 品牌周排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBrandWeekRank(String category){
        return insRkBrandWeekRepository.getMaxCreateTime(category);
    }

    /**
     * 品牌周排行榜分页
     * @return
     */
    public Page<BrandRankDto> getBrandWeekRankPage(InsRkSearch followerSearch){
        return getBrandLogo(insRkBrandWeekRepository.findPage(followerSearch));
    }

    /**
     * 品牌周排行榜列表
     * @return
     */
    public List<BrandRankDto> getBrandWeekRankList(InsRkSearch followerSearch,int size){
        return insRkBrandWeekRepository.findList(followerSearch,size);
    }

    /**
     * 品牌月排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBrandMonthRank(String category){
        return insRkBrandMonthRepository.getMaxCreateTime(category);
    }

    /**
     * 品牌月排行榜分页
     * @return
     */
    public Page<BrandRankDto> getBrandMonthRankPage(InsRkSearch followerSearch){
        return getBrandLogo(insRkBrandMonthRepository.findPage(followerSearch));
    }

    /**
     * 品牌月排行榜列表
     * @return
     */
    public List<BrandRankDto> getBrandMonthRankList(InsRkSearch followerSearch,int size){
        return insRkBrandMonthRepository.findList(followerSearch,size);
    }

    /**
     * 品牌日期列表
     * @return
     */
    public Map<String,Object> getBrandRankingDate(String category){
        Map<String,Object> ret = new HashMap<>();
        var dailyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(1)),"yyyyMMdd").minusMonths(1);
        var weeklyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(2)),"yyyyMMdd").minusMonths(3);
        var monthlyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(3)),"yyyyMMdd").minusYears(1);
        val dailyDate = getDailyDate(insRkBrandDayRepository.findDateCode(category, Integer.parseInt(DateUtil.format(dailyDateLocalDate, "yyyyMMdd")),RANK_DATE_DAY_SIZE));
        val weeklyDate = getWeeklyDate(insRkBrandWeekRepository.findDateCode(category, Integer.parseInt(DateUtil.format(weeklyDateLocalDate, "yyyyMMdd")),RANK_DATE_WEEK_SIZE));
        val monthlyDate = getMonthlyDate(insRkBrandMonthRepository.findDateCode(category, Integer.parseInt(DateUtil.format(monthlyDateLocalDate, "yyyyMM")),RANK_DATE_MONTH_SIZE));
        ret.put("dailyDate",dailyDate);
        ret.put("weeklyDate",weeklyDate);
        ret.put("monthlyDate",monthlyDate);
        return ret;
    }


    //########带货达人
    /**
     * 带货达人天排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBloggerBgsDayRank(String category){
        return insRkBloggerBgsDayRepository.getMaxCreateTime(category);
    }

    public int getBloggerBgsNewestDateCode(InsRkSearch insRkSearch){
        if(insRkSearch.getRankType() == 1){
            return insRkBloggerBgsWeekRepository.getMaxDateCode(insRkSearch.getCategoryName());
        }else if(insRkSearch.getRankType() == 2){
            return insRkBloggerBgsMonthRepository.getMaxDateCode(insRkSearch.getCategoryName());
        }
        return insRkBloggerBgsDayRepository.getMaxDateCode(insRkSearch.getCategoryName());
    }

    /**
     * 带货达人天排行榜分页
     * @return
     */
    public Page<RankDto> getBloggerBgsDayRankPage(InsRkSearch followerSearch){
        return insRkBloggerBgsDayRepository.findPage(followerSearch);
    }

    /**
     * 带货达人天排行榜列表
     * @return
     */
    public List<RankDto> getBloggerBgsDayRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerBgsDayRepository.findList(followerSearch,size);
    }

    /**
     * 带货达人周排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBloggerBgsWeekRank(String category){
        return insRkBloggerBgsWeekRepository.getMaxCreateTime(category);
    }

    /**
     * 带货达人周排行榜分页
     * @return
     */
    public Page<RankDto> getBloggerBgsWeekRankPage(InsRkSearch followerSearch){
        return insRkBloggerBgsWeekRepository.findPage(followerSearch);
    }

    /**
     * 带货达人周排行榜列表
     * @return
     */
    public List<RankDto> getBloggerBgsWeekRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerBgsWeekRepository.findList(followerSearch,size);
    }

    /**
     * 带货达人月排行榜最新更新时间
     * @return
     */
    public long getUpdateTimeByBloggerBgsMonthRank(String category){
        return insRkBloggerBgsMonthRepository.getMaxCreateTime(category);
    }

    /**
     * 带货达人月排行榜分页
     * @return
     */
    public Page<RankDto> getBloggerBgsMonthRankPage(InsRkSearch followerSearch){
        return insRkBloggerBgsMonthRepository.findPage(followerSearch);
    }

    /**
     * 带货达人月排行榜列表
     * @return
     */
    public List<RankDto> getBloggerBgsMonthRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerBgsMonthRepository.findList(followerSearch,size);
    }

    public Page<BrandRankDto> getBrandLogo(Page<BrandRankDto> rankDtoPage){
        rankDtoPage.getList().forEach( brandResp -> {
            String logo = commonBrandRepository.findCommonBrandMoreFansBloggerPic((int)brandResp.getId());
            brandResp.setLogo(logo);
        });
        return rankDtoPage;
    }

    /**
     * 带货达人日期列表
     * @return
     */
    public Map<String,Object> getBloggerBgsRankingDate(String category){
        Map<String,Object> ret = new HashMap<>();
        var dailyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(1)),"yyyyMMdd").minusMonths(1);
        var weeklyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(2)),"yyyyMMdd").minusMonths(3);
        var monthlyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(3)),"yyyyMMdd").minusYears(1);
        val dailyDate = getDailyDate(insRkBloggerBgsDayRepository.findDateCode(category, Integer.parseInt(DateUtil.format(dailyDateLocalDate, "yyyyMMdd")),RANK_DATE_DAY_SIZE));
        val weeklyDate = getWeeklyDate(insRkBloggerBgsWeekRepository.findDateCode(category, Integer.parseInt(DateUtil.format(weeklyDateLocalDate, "yyyyMMdd")),RANK_DATE_WEEK_SIZE));
        val monthlyDate = getMonthlyDate(insRkBloggerBgsMonthRepository.findDateCode(category, Integer.parseInt(DateUtil.format(monthlyDateLocalDate, "yyyyMM")),RANK_DATE_MONTH_SIZE));
        ret.put("dailyDate",dailyDate);
        ret.put("weeklyDate",weeklyDate);
        ret.put("monthlyDate",monthlyDate);
        return ret;
    }



    public Map<String,Object> getRankingDate(String category){
        Map<String,Object> ret = new HashMap<>();
        var dailyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(1)),"yyyyMMdd").minusMonths(1);
        var weeklyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(2)),"yyyyMMdd").minusMonths(3);
        var monthlyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(3)),"yyyyMMdd").minusYears(1);
        val dailyDate = getDailyDate(insRkBloggerFgDayRepository.findDateCode(category, Integer.parseInt(DateUtil.format(dailyDateLocalDate, "yyyyMMdd")),RANK_DATE_DAY_SIZE));
        val weeklyDate = getWeeklyDate(insRkBloggerFgWeekRepository.findDateCode(category, Integer.parseInt(DateUtil.format(weeklyDateLocalDate, "yyyyMMdd")),RANK_DATE_WEEK_SIZE));
        val monthlyDate = getMonthlyDate(insRkBloggerFgMonthRepository.findDateCode(category, Integer.parseInt(DateUtil.format(monthlyDateLocalDate, "yyyyMM")),RANK_DATE_MONTH_SIZE));
        ret.put("dailyDate",dailyDate);
        ret.put("weeklyDate",weeklyDate);
        ret.put("monthlyDate",monthlyDate);
        return ret;
    }

    private int getDefaultDate(int ranking){
        int dateCode;
        switch (ranking){
            case 2:
                dateCode =  getLastWeekDay();
                break;
            case 3:
                dateCode = getLastMonthDay();
                break;
            default:
                dateCode = Integer.parseInt(DateUtil.format(LocalDateTime.now().minusDays(1),"yyyyMMdd"));
                break;
        }
        return dateCode;
    }


    private List<Map<String,Object>> getDailyDate(List<Integer> dailyDates){
        List<Map<String,Object>> datas = new ArrayList<>();

        for (Integer dailyDate : dailyDates) {
            Map<String,Object> data = new HashMap<>();
            data.put("dateCode",dailyDate);
            data.put("dateDesc", DateUtil.parseLocalDateTime(dailyDate.toString(),"yyyyMMdd").format(dateTimeFormatter));
            datas.add(data);
        }
        return datas;
    }

    private List<Map<String,Object>> getWeeklyDate(List<Integer> weeklyDates){
        List<Map<String,Object>> datas = new ArrayList<>();

        for (Integer weekly : weeklyDates) {
            Map<String,Object> data = new HashMap<>();
            data.put("dateCode",weekly);
            var endDay = DateUtil.parseLocalDateTime(weekly.toString(),"yyyyMMdd");
            var startDay = endDay.minusDays(6);

            if(startDay.format(DateTimeFormatter.ofPattern("yyyy")).equals(endDay.format(DateTimeFormatter.ofPattern("yyyy")))){
                data.put("dateDesc",startDay.format(DateTimeFormatter.ofPattern("MMM dd", Locale.ENGLISH))+"-"+endDay.format(dateTimeFormatter));
            }else {
                data.put("dateDesc",startDay.format(dateTimeFormatter)+"-"+endDay.format(dateTimeFormatter));
            }
            datas.add(data);
        }
        return datas;
    }

    private List<Map<String,Object>> getMonthlyDate(List<Integer> monthlyDates){
        List<Map<String,Object>> datas = new ArrayList<>();

        for (Integer monthly : monthlyDates) {
            Map<String,Object> data = new HashMap<>();
            data.put("dateCode",monthly);
            DateTime dateTime = DateUtil.parse(monthly.toString(),"yyyyMM");
            data.put("dateDesc",dateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().format(DateTimeFormatter.ofPattern("MMMM yyyy", Locale.ENGLISH)));
            datas.add(data);
        }
        return datas;
    }

    private int getLastWeekDay(){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -1*7);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return Integer.parseInt(DateUtil.format(cal.getTime(),"yyyyMMdd"));
    }

    private int getLastMonthDay(){
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -1);
        cal.set(Calendar.DAY_OF_MONTH,1);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return Integer.parseInt(DateUtil.format(cal.getTime(),"yyyyMMdd"));
    }

    /**
     * 获取企业合作者月排行列表
     * @return
     */
    public Page<RankDto> getAdecMonthRankPage(InsRkSearch followerSearch){
        return insRkBloggerAdecMonthRepository.findPage(followerSearch);
    }

    /**
     * 获取企业合作者周排行列表
     * @return
     */
    public Page<RankDto> getAdecWeekRankPage(InsRkSearch followerSearch){
        return insRkBloggerAdecWeekRepository.findPage(followerSearch);
    }

    /**
     * 获取企业合作者排行列表
     * @return
     */
    public List<RankDto> getAdecWeekRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerAdecWeekRepository.findList(followerSearch,size);
    }

    /**
     * 获取企业合作者排行列表
     * @return
     */
    public List<RankDto> getAdecMonthRankList(InsRkSearch followerSearch,int size){
        return insRkBloggerAdecMonthRepository.findList(followerSearch,size);
    }

    /**
     * 获取企业合作者榜最新更新时间
     * @return
     */
    public long getUpdateTimeByAdecWeekRank(String category){
        return insRkBloggerAdecWeekRepository.getMaxCreateTime(category);
    }

    /**
     * 获取企业合作者榜最新更新时间
     * @return
     */
    public long getUpdateTimeByAdecMonthRank(String category){
        return insRkBloggerAdecMonthRepository.getMaxCreateTime(category);
    }

    /**
     * 获取企业合作者榜的日期
     * @param category
     * @return
     */
    public Map<String,Object> getAdecRankingDate(String category){
        Map<String,Object> ret = new HashMap<>();
        var weeklyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(2)),"yyyyMMdd").minusMonths(3);
        var monthlyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(3)),"yyyyMMdd").minusYears(1);
        val weeklyDate = getWeeklyDate(insRkBloggerAdecWeekRepository.findDateCode(category, Integer.parseInt(DateUtil.format(weeklyDateLocalDate, "yyyyMMdd")),RANK_DATE_WEEK_SIZE));
        val monthlyDate = getMonthlyDate(insRkBloggerAdecMonthRepository.findDateCode(category, Integer.parseInt(DateUtil.format(monthlyDateLocalDate, "yyyyMM")),RANK_DATE_MONTH_SIZE));
        ret.put("weeklyDate",weeklyDate);
        ret.put("monthlyDate",monthlyDate);
        return ret;
    }

    /**
     * 粉丝排行榜最新排行时间
     * @return
     */
    public int getMaxDateCodeByAdecWeekRank(String category){
        return insRkBloggerAdecWeekRepository.getMaxDateCode(category);
    }

    /**
     * 商品排行榜分页
     * @param insRkSearch
     * @return
     */
    public Page<ProductRankDto> getProductRankPage(InsRkSearch insRkSearch){
        if(insRkSearch.getDate() == 0){
            insRkSearch.setDate(getProductNewestDateCode(insRkSearch));
        }
        if(insRkSearch.getRankType() == 1){
            return insRkProductMonthRepository.getPage(insRkSearch);
        }
        return insRkProductWeekRepository.getPage(insRkSearch);
    }

    /**
     * 商品排行榜列表
     * @param insRkSearch
     * @return
     */
    public List<ProductRankDto> getProductRankList(InsRkSearch insRkSearch,int size){
        if(insRkSearch.getRankType() == 1){
            return insRkProductMonthRepository.getList(insRkSearch,size);
        }
        return insRkProductWeekRepository.getList(insRkSearch,size);
    }

    /**
     * 获取商品排行榜最新的日期码
     * @param insRkSearch
     * @return
     */
    public int getProductNewestDateCode(InsRkSearch insRkSearch){
        if(insRkSearch.getRankType() == 1){
            return insRkProductMonthRepository.getMxDateCode(insRkSearch.getCategoryName());
        }
        return insRkProductWeekRepository.getMxDateCode(insRkSearch.getCategoryName());
    }

    /**
     * 获取商品排行榜最新的更新日期
     * @param insRkSearch
     * @return
     */
    public long getProductNewestUpdateDate(InsRkSearch insRkSearch){
        if(insRkSearch.getRankType() == 1){
            return insRkProductMonthRepository.getMaxCreateTime(insRkSearch.getCategoryName());
        }
        return insRkProductWeekRepository.getMaxCreateTime(insRkSearch.getCategoryName());
    }


    /**
     * 获取商品排行榜的日期
     * @return
     */
    public Map<String,Object> getProductRankDate(){
        Map<String,Object> ret = new HashMap<>();
        var weeklyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(2)),"yyyyMMdd").minusMonths(3);
        var monthlyDateLocalDate = DateUtil.parseLocalDateTime(String.valueOf(getDefaultDate(3)),"yyyyMMdd").minusYears(1);
        val weeklyDate = getWeeklyDate(insRkProductWeekRepository.findDateCode("",Integer.parseInt(DateUtil.format(weeklyDateLocalDate, "yyyyMMdd")),RANK_DATE_WEEK_SIZE));
        val monthlyDate = getMonthlyDate(insRkProductMonthRepository.findDateCode("",Integer.parseInt(DateUtil.format(monthlyDateLocalDate, "yyyyMM")),RANK_DATE_MONTH_SIZE));
        ret.put("weeklyDate",weeklyDate);
        ret.put("monthlyDate",monthlyDate);
        return ret;
    }
}
